class Queue{
    /*
    tag :
        AR_LONG 'A'     // array of longs
        AR_STR  'S'     // array of strings
    */
    Queue(tag, name, len){
        this.tag = tag;
        this.name = name;
        this.len = len;

        this.start = 0;
        this.end = 0;
        this.createArray();
    }

    ~Queue(){
        DeleteArray(this.ca);
    }

    createArray(){
        this.ca = GetArrayId(this.name);
        if(this.ca != -1){
            DeleteArray(this.ca);
        }
        this.ca = CreateArray(this.name);
    }

    initQueue(){
        if(this.start == 0 && this.end == 0){
            return;
        }

        this.start = 0;
        this.end = 0;
    }

    push(value){
        if(this.tag == AR_STR){
            SetArrayString(this.ca, this.end, value);
        } else {
            SetArrayLong(this.ca, this.end, value);
        }
        this.end = this.end + 1;

        while((this.end - this.start) > this.len){
            this.start = this.start + 1;
        }
    }

    getLast(){
        return GetArrayElement(this.tag, this.ca, this.end - 1);
    }

    diff(minArray){
        auto maxLen = this.end - this.start;
        auto minLen = minArray.end - minArray.start;

        auto i, maxTmp, minTmp;
        auto minFirst = GetArrayElement(this.tag, minArray.ca, minArray.end - 1);
        auto maxStartSearch = this.end - 1 - minLen;
        for(i = maxStartSearch; i >= this.start + minLen - 1; i = i - 1){
            maxTmp = GetArrayElement(this.tag, this.ca, i);
            if(minFirst != maxTmp){
                continue;
            }

            auto j = i - 1;
            auto k = minArray.end - 2;
            for(; k >= minArray.start; j = j - 1, k = k - 1){
                maxTmp = GetArrayElement(this.tag, this.ca, j);
                minTmp = GetArrayElement(this.tag, minArray.ca, k);
                if(maxTmp != minTmp){
                    break;
                }
            }

            if(k == minArray.start - 1){
                return GetArrayElement(this.tag, this.ca, maxStartSearch);
            }
        }
        return 0x0;
    }

    checkFor(minArray){
        auto maxLen = this.end - this.start;
        auto minLen = minArray.end - minArray.start;

        auto i, maxTmp, minTmp, tmp, forCount;
        auto minFirst = GetArrayElement(this.tag, minArray.ca, minArray.end - 1);
        auto minSecond = GetArrayElement(this.tag, minArray.ca, minArray.end - 2);
        auto maxStartSearch = this.end - 1 - minLen;
        forCount = 0;
        for(i = maxStartSearch; i >= this.start + minLen - 1; i = i - 1){
            maxTmp = GetArrayElement(this.tag, this.ca, i);
            if(minFirst != maxTmp){
                continue;
            }

            tmp =  GetArrayElement(this.tag, this.ca, i - 1);
            if(minSecond != tmp){
                continue;
            }

            forCount = forCount + 1;
            if(forCount >= 5){
                return 1;
            }
        }
        return -1;
    }

    queueEcho(){
        auto i;
        Message("%s:", this.name);
        for(i = this.end - 1; i >= this.start; i = i - 1){
            if(this.tag == AR_STR){
                Message("%s,", GetArrayElement(AR_STR, this.ca, i));
            } else {
                Message("0x%x,", GetArrayElement(AR_LONG, this.ca, i));
            }
            
        }
        Message("\n start: %d, end: %d\n\n", this.start, this.end);
    }
}

